#pragma once
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cassert>

namespace cr
{
    template <class T, class ref, class ptr>
    class __iterator
    {
    public:
        typedef ref rref;
        typedef ptr rptr;

    public:
        __iterator()
            : _p(nullptr)
        {
        }

        __iterator(ptr tmp)
            : _p(tmp) {}

        __iterator(const __iterator &tmp)
            : _p(tmp._p) {}

        const __iterator &operator=(__iterator tmp)
        {
            std::swap(_p, tmp._p);
            return *this;
        }

        ref operator*() const
        {
            return *_p;
        }
        ref operator[](size_t i)
        {
            return _p[i];
        }
        ptr operator+(int pos)
        {
            return _p + pos;
        }
        ptr operator-(int pos) const
        {
            return _p - pos;
        }
        int operator-(const __iterator &it) const
        {
            return _p - it._p;
        }
        ptr operator++() // 前置
        {
            return ++_p;
        }
        ptr operator++(int) // 后置
        {
            return _p++;
        }
        ptr operator--() // 前置
        {
            return --_p;
        }
        ptr operator--(int) // 后置
        {
            return _p--;
        }
        bool operator!=(const __iterator &tmp) const
        {
            return _p != tmp._p;
        }
        bool operator==(const __iterator &tmp) const
        {
            return _p == tmp._p;
        }

    public:
        ptr _p;
    };

    template <class iterator>
    class __reverse_iterator
    {
    public:
        typedef typename iterator::rref ref;
        typedef typename iterator::rptr ptr;

    public:
        __reverse_iterator(iterator it)
            : _it(it)
        {
        }

        ref operator*()
        {
            return *_it;
        }
        ptr operator++() // 前置
        {
            return --_it;
        }
        ptr operator++(int) // 后置
        {
            return _it--;
        }
        ptr operator--() // 前置
        {
            return ++_it;
        }
        ptr operator--(int) // 后置
        {
            return _it++;
        }
        bool operator!=(const __reverse_iterator &tmp) const
        {
            return _it != tmp._it;
        }
        bool operator==(const __reverse_iterator &tmp) const
        {
            return _it != tmp._it;
        }

    private:
        iterator _it;
    };

    template <class T>
    class Vector
    {
    public:
        typedef __iterator<T, T &, T *> iterator;
        typedef __iterator<T, const T &, const T *> const_iterator;
        typedef __reverse_iterator<iterator> reverse_iterator;
        typedef __reverse_iterator<const_iterator> const_reverse_iterator;

        iterator begin()
        {
            return _start;
        }
        iterator end()
        {
            return _finish;
        }
        const_iterator cbegin() const
        {
            return _start;
        }
        const_iterator cend() const
        {
            return _finish;
        }

        reverse_iterator rbegin()
        {
            return iterator(_finish - 1);
        }
        reverse_iterator rend()
        {
            return iterator(_start - 1);
        }
        const_reverse_iterator crbegin() const
        {
            return _finish - 1;
        }
        const_reverse_iterator crend() const
        {
            return _start - 1;
        }

    public:
        ~Vector()
        {
            if (_start._p)
            {
                delete[] _start._p;
                _start = _finish = _end = nullptr;
            }
        }

        Vector() {}
        Vector(size_t n, const T &val = T()) // 临时对象具有常性
        {
            reserve(n);
            while (n--)
            {
                *_finish = val;
                _finish++;
            }
        }

        // 迭代器构造方式，但是在参数匹配上可能存在问题
        // 两个参数类型相同可能就会默认进行迭代器初始化
        template <class input_iterator>
        Vector(input_iterator begin, input_iterator end)
        {
            while (begin != end)
            {
                push_back(*begin);
                begin++;
            }
        }
        // 针对vector<int> v(3,1);方式调用上面迭代器方式构造
        Vector(int n, const T &val = T()) // 临时对象具有常性
        {
            reserve(n);
            while (n--)
            {
                *_finish = val;
                _finish++;
            }
        }

        // 拷贝构造+移动构造
        Vector(const Vector &tmp)
        {
            reserve(tmp.capacity());   
            /*for (auto it : tmp)
            {
                *_finish = it;
                _finish++;
            }*/
            auto it = tmp.cbegin();
            while (it != tmp.cend())
            {
                *_finish = *it;
                _finish++;
                it++;
            }
        }
        Vector(Vector &&tmp)
        {
            swap(tmp);
        }
        // 赋值重载+移动赋值
        Vector &operator=(Vector tmp) // 通过拷贝构造接收
        {
            swap(tmp);
            return *this;
        }
        Vector &operator=(Vector &&tmp)
        {
            swap(tmp);
            return *this;
        }

        void swap(Vector &tmp)
        {
            // 类型必须完全匹配，Vector如果是const的话就会导致参数二具有const属性
            std::swap(_start._p, tmp._start._p);
            std::swap(_finish._p, tmp._finish._p);
            std::swap(_end._p, tmp._end._p);
        }

        void reserve(size_t n)
        {
            // reserve不支持变小
            if (n <= capacity())
                return;
            T *tmp = new T[n];
            // 不能进行memmove方式拷贝(浅拷贝)
            //  如果T类型是自定义成员或者内部存在指针指向的话
            //  拷贝就会导致新旧内容指向的空间实际上是一样的，所以出作用域就析构没了
            //  memmove(tmp, _start, sizeof(T) * size());
            int sz = size();
            // 如果_start和_finshi都为空的话size()就为0
            for (int i = 0; i < sz; i++)
            {
                tmp[i] = _start[i]; // 内部是自定义成员的话就会调用其负值重载函数
            }

            // 先修改_start的话，size也会跟着被修改
            _finish = tmp + size();
            _end = tmp + n;
            std::swap(_start._p, tmp); // 类型必须完全匹配
            delete[] tmp;
        }

        void resize(size_t n, const T &val = T())
        {
            // 当空间小于size()时会进行缩容,不会进行数据更改
            if (n < size())
            {
                _finish = _start + n;
                return;
            }

            // 只会将扩容的部分进行数据更改
            reserve(n);
            for (int i = size(); i < n; i++)
            {
                _start[i] = val;
            }
            _finish = _start + n;
        }

        void push_back(const T &val)
        {
            if (_end == _finish)
            {
                int newcap = capacity() == 0 ? 8 : capacity() * 2;
                reserve(newcap);
            }
            *_finish = val;
            _finish++;
        }

        template <class... Args>
        void emplace_back(Args &&...args) // 引用折叠+可变参数
        {
            if (_end == _finish)
            {
                int newcap = capacity() == 0 ? 8 : capacity() * 2;
                reserve(newcap);
            }
            // 定位new实现原地构造
            new (_start + size()) T(std::forward<Args>(args)...);
            _finish++;
        }

        void pop_back()
        {
            _finish--;
        }

        iterator insert(const iterator &pos, const T &val)
        {
            int index = pos - _start; // 记录需要插入的位置下标
            assert(index <= size());
            if (_end == _finish)
            {
                int newcap = capacity() == 0 ? 8 : capacity() * 2;
                reserve(newcap);
            }
            int n = size();
            _finish++; // 有效数据+1
            while (n > index)
            {
                _start[n] = _start[n - 1];
                n--;
            }
            _start[index] = val;
            return _start + index;
        }

        iterator erase(const iterator &pos)
        {
            int index = pos - _start;
            while (index < size() - 1)
            {
                _start[index] = _start[index + 1];
                index++;
            }
            _finish--;
            return _start + index;
        }

        T &operator[](size_t pos)
        {
            assert(pos < size());
            return _start[pos];
        }
        const T &operator[](size_t pos) const
        {
            assert(pos < size());
            return _start[pos];
        }
        T &front()
        {
            return *_start;
        }

        const T &front() const
        {
            return *_start;
        }

        T &back()
        {
            return *(_finish - 1);
        }

        const T &back() const
        {
            return *(_finish - 1);
        }

        size_t size() const
        {
            return _finish - _start;
        }
        size_t capacity() const
        {
            return _end - _start;
        }
        bool empty() const
        {
            return size() == 0;
        }

    private:
        iterator _start;  // 指向数据块的开始
        iterator _finish; // 指向有效数据的尾
        iterator _end;    // 指向存储容量的尾
    };

    template <class T>
    std::ostream &operator<<(std::ostream &out, Vector<T> &v)
    {
        // auto it = v.begin();
        // while (it != v.end())
        //{
        //     out << *it << ' ';
        //     it++;
        // }
        for (const T &it : v)
        {
            out << it << ' ';
        }
        out << std::endl;
        return out;
    }
}